

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <linux/stddef.h>
#include <errno.h>
#include <signal.h>
#include <syslog.h>
#include <netdb.h>
#include <time.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <netinet/tcp.h>
#include <netinet/if_ether.h>
#include <linux/if_packet.h>
#include <stdio.h>

#include "private_type.h"
#include "private_log.h"

#include "timer.h"
//#include "raw_packet.h"


static timer_element_t timer_queue[MAX_TIMER_NUMS];
static int init_first_run = 0;
int TIMER_GetSystemRunTime(struct timeval *pstTimeValue)
{
	struct timespec recvTime;

    if(NULL == pstTimeValue)
    {
        return -1;
    }
    memset(&recvTime,0,sizeof(struct timespec));
    clock_gettime(CLOCK_MONOTONIC, &recvTime);

    pstTimeValue->tv_sec = recvTime.tv_sec;
    pstTimeValue->tv_usec = recvTime.tv_nsec/1000;

    return 0;
}

void timer_init(void)
{
	memset(&timer_queue, 0, sizeof(timer_queue));
}

int timer_register(uint duration, uint first_run, timer_func_t func, void *data, timer_exit_t on_exit, char *desc)
{
	int i;
	struct timeval tv;

	for(i = 0; i < MAX_TIMER_NUMS; i ++) {
		if(timer_queue[i].valid == 0) break;
	}

	if(i >= MAX_TIMER_NUMS) {
		CW_SendErr("Timer queue full!");
		return -1;
	}

	timer_queue[i].data = data;
	TIMER_GetSystemRunTime(&tv);
	timer_queue[i].issue_time.tv_sec = tv.tv_sec;
	timer_queue[i].issue_time.tv_usec = tv.tv_usec;
	timer_queue[i].next_time = (UINT64)tv.tv_sec * 1000 + tv.tv_usec / 1000;
	timer_queue[i].duration = duration;
	timer_queue[i].timer_func = func;
	timer_queue[i].on_exit = on_exit;
	timer_queue[i].privates = 0;
    memset(timer_queue[i].desc, 0, sizeof(timer_queue[i].desc));

	strncpy(timer_queue[i].desc, desc, sizeof(timer_queue[i].desc));
	timer_queue[i].valid = 1;

	if (!first_run){
		timer_queue[i].next_time += timer_queue[i].duration;
	}
	return i;
}

void timer_reschedule(int handle, int second, int reason)
{
	struct timeval tv;

	TIMER_GetSystemRunTime(&tv);
	timer_queue[handle].next_time = (UINT64)(tv.tv_sec + second) * 1000 + tv.tv_usec / 1000;
	timer_queue[handle].schedule_reason = reason;
	init_first_run = 1;
}

int timer_cancel(int handle)
{
	if (handle < MAX_TIMER_NUMS){
		timer_queue[handle].valid = 0;
		if (timer_queue[handle].on_exit){
			timer_queue[handle].on_exit(&timer_queue[handle]);
		}

        memset(&timer_queue[handle], 0, sizeof(timer_queue[handle]));
		return 0;
	}
	return -1;
}


int timer_set_duration(int handle, int duration)
{
	if ((handle < MAX_TIMER_NUMS) && (timer_queue[handle].valid)){
		timer_queue[handle].duration = duration;
	}
	return -1;
}


void timer_scheduler(void)
{
	int i, ret;
	struct timeval tv;
	UINT64 ts, old_ts;

//	CW_SendErr("TS");

	//raw_packet_timeout(); // Always process raw packet timeout

	TIMER_GetSystemRunTime(&tv);
	ts = (UINT64)tv.tv_sec * 1000 + tv.tv_usec / 1000;

	if(!init_first_run) {
		init_first_run = 1;
		for(i = 0; i < MAX_TIMER_NUMS; i++) {
			if(timer_queue[i].valid) {
				old_ts = (UINT64)timer_queue[i].issue_time.tv_sec * 1000 + timer_queue[i].issue_time.tv_usec / 1000;
				timer_queue[i].issue_time.tv_sec = tv.tv_sec;
				timer_queue[i].issue_time.tv_usec = tv.tv_usec;
				timer_queue[i].next_time += (ts - old_ts);
			}
		}
	}

//	CW_SendErr("TS: %lld:%lld\n", ts, );
	for(i = 0; i < MAX_TIMER_NUMS; i++) {
		if(timer_queue[i].valid) {
//			CW_SendErr("TS: %d:%lld:%lld\n", i, ts, timer_queue[i].next_time);
			if(ts > timer_queue[i].next_time) {
				if(timer_queue[i].timer_func) {
					timer_queue[i].issue_time.tv_sec = tv.tv_sec;
					timer_queue[i].issue_time.tv_usec = tv.tv_usec;
					ret = timer_queue[i].timer_func(&timer_queue[i], timer_queue[i].data);
					switch(ret) {
					case TIMER_RUN_FOREVER:
						timer_queue[i].next_time += timer_queue[i].duration;
						timer_queue[i].schedule_reason	= REASON_TIMER;
						break;
					case TIMER_RUN_ONCE:
						timer_cancel(i);
						break;
					default:
						CW_SendErr("Invalid timer function return value: %d", ret);
					}
				}
				else {
					CW_SendErr("Empty function timer element");
				}
			}
		}
	}
}

/*
	When system time change, the timer need to be reset the nexttime . otherwise it will continue run
*/

void timer_reschedule_all(void)
{
	int i;
	struct timeval tv;
	for(i = 0; i < MAX_TIMER_NUMS; i++) {
		if(timer_queue[i].valid) {
			TIMER_GetSystemRunTime(&tv);
			timer_queue[i].next_time = (UINT64)(tv.tv_sec) * 1000 + tv.tv_usec / 1000;
			timer_queue[i].schedule_reason = REASON_SYSTIME;
		}
	}
}

